package com.cn.xact.ty_treasured_book.net;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import com.cn.xact.ty_treasured_book.TYUserState;
import com.cn.xact.ty_treasured_book.net.base.NetworkInterface;
import com.cn.xact.ty_treasured_book.net.demo.MockRequestPathGenerater;
import com.cn.xact.ty_treasured_book.util.xmlparser.ExtXMLItem;
import com.cn.xact.ty_treasured_book.util.xmlparser.ExtXMLParse;
import com.cn.xact.ty_treasured_book.util.xmlparser.ExtXMLUtil;

public class NetworkImpl implements NetworkInterface {

    private Context mContext;
    private ProgressDialog netWaiting;
    private NetworkCallBack mCallBack;

    private ExtXMLParse myXMLParser = new ExtXMLParse();
    private ExtXMLUtil myXMLUtil = new ExtXMLUtil();
    private ExtXMLItem myParsedItem = new ExtXMLItem();

    private static final int NET_WORK_MESSAGE_NET_BEGIN = 1;
    private static final int NET_WORK_MESSAGE_NET_FINISH = 2;

    public static final int NET_WORK_ID_LOGIN = 1;
    public static final int NET_WORK_ID_GET_SUPPORT_PHONES = 2;
    public static final int NET_WORK_ID_GET_NEW_MSG = 3;
    public static final int NET_WORK_ID_GET_ALL_MSG = 4;
    public static final int NET_WORK_ID_GET_USER_INFO = 5;
    public static final int NET_WORK_ID_GET_EXCHANGE_LIST = 6;
    public static final int NET_WORK_ID_GET_EXCHANGE_HISTORY = 7;
    public static final int NET_WORK_ID_GET_RANK = 8;
    public static final int NET_WORK_ID_GET_RULES = 9;
    public static final int NET_WORK_ID_SET_USER_INFO = 10;
    public static final int NET_WORK_ID_GET_VERIFY_CODE = 11;
    public static final int NET_WORK_ID_SET_USER_PSW = 12;
    public static final int NET_WORK_ID_CREDIT_EXCHANGE = 13;
    public static final int NET_WORK_ID_REGISTER = 14;
    public static final int NET_WORK_ID_DOWNLOAD_FILES = 15;
    public static final int NET_WORK_ID_GET_APP_COMMENTS = 16;
    public static final int NET_WORK_ID_PUBLISH_COMMENTS = 17;

    Handler mH;

    private Bitmap[] mCurBitmaps;
    private String mFilePath;

    public NetworkImpl(Context context, NetworkCallBack callback) {
        mContext = context;
        netWaiting = new ProgressDialog(context);
        netWaiting.setMessage("Please wait");
        netWaiting.setCanceledOnTouchOutside(false);
        mCallBack = callback;

        mH = new Handler(mContext.getMainLooper()) {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case NET_WORK_MESSAGE_NET_BEGIN:
                    begin();
                    break;
                case NET_WORK_MESSAGE_NET_FINISH:
                    end((int)msg.arg1, (int)msg.arg2);
                    break;
                }
            }
        };
    }

    private void begin() {
        netWaiting.show();
    }

    private void end(int OP, int attach) {
        boolean success = true;
        String[] arrayResults1 = null;
        String[] arrayResults2 = null;
        List<Map<String, Object>> listResult = null;
        String stringResult = null;
        Map<String, Object> mapResult = null;
        int size = 0;
        netWaiting.dismiss();
        switch(OP) {
        case NET_WORK_ID_LOGIN:
        case NET_WORK_ID_SET_USER_INFO:
        case NET_WORK_ID_SET_USER_PSW:
        case NET_WORK_ID_CREDIT_EXCHANGE:
        case NET_WORK_ID_REGISTER:
        case NET_WORK_ID_PUBLISH_COMMENTS:
            if (isValidValue(myParsedItem.getValueByName("result"))) {
                success = (Integer.valueOf(myParsedItem.getValueByName("result")) == 1);
                stringResult = myParsedItem.getValueByName("reason");
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, stringResult, null);
            }
            break;
        case NET_WORK_ID_GET_SUPPORT_PHONES:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                success = size > 0;
                arrayResults1 = new String[size];
                arrayResults1[0] = myParsedItem.getValueByName("name");
                for (int i = 1; i < size; i++) {
                    arrayResults1[i] = myParsedItem.getValueByName("name" + i);
                }
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, arrayResults1, null);
            }
            break;
        case NET_WORK_ID_GET_NEW_MSG:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                success = size > 0;
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, size, null);
            }
            break;
        case NET_WORK_ID_GET_ALL_MSG:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                arrayResults1 = new String[size];
                arrayResults2 = new String[size];
                arrayResults1[0] = myParsedItem.getValueByName("date");
                arrayResults2[0] = myParsedItem.getValueByName("msg");
                for (int i = 1; i < size; i++) {
                    arrayResults1[i] = myParsedItem.getValueByName("date" + i);
                    arrayResults2[i] = myParsedItem.getValueByName("msg" + i);
                }
                success = size > 0;
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, arrayResults1, arrayResults2);
            }
            break;
        case NET_WORK_ID_GET_USER_INFO:
            if (isValidValue(myParsedItem.getValueByName("login_conter"))
                    && isValidValue(myParsedItem.getValueByName("credit"))
                    && isValidValue(myParsedItem.getValueByName("rank"))
                    && isValidValue(myParsedItem.getValueByName("gender"))
                    && isValidValue(myParsedItem.getValueByName("result"))) {
                TYUserState.updateUserState(
                          Integer.valueOf(myParsedItem.getValueByName("login_conter"))
                        , Integer.valueOf(myParsedItem.getValueByName("credit"))
                        , Integer.valueOf(myParsedItem.getValueByName("rank"))
                        , Integer.valueOf(myParsedItem.getValueByName("gender"))
                        , myParsedItem.getValueByName("icon")
                        , myParsedItem.getValueByName("nick"));
                success = (Integer.valueOf(myParsedItem.getValueByName("result")) == 1);
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, null, null);
            }
            break;
        case NET_WORK_ID_GET_EXCHANGE_LIST:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                 size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                 listResult = new ArrayList<Map<String, Object>>();
                 mapResult = new HashMap<String, Object>();
                 mapResult.put("icon",  mCurBitmaps[0]);
                 mapResult.put("title", myParsedItem.getValueByName("name"));
                 mapResult.put("cost",  myParsedItem.getValueByName("credit"));
                 listResult.add(mapResult);
                 for (int i = 1; i < size; i++) {
                     mapResult = new HashMap<String, Object>();
                     mapResult.put("icon",  mCurBitmaps[i]);
                     mapResult.put("title", myParsedItem.getValueByName("name" + i));
                     mapResult.put("cost",  myParsedItem.getValueByName("credit" + i));
                     listResult.add(mapResult);
                 }
                 success = size > 0;
             } else {
                 success = false;
             }
             if (mCallBack != null) {
                 mCallBack.onNetworkCallBack(OP, success, listResult, null);
             }
            break;
        case NET_WORK_ID_GET_EXCHANGE_HISTORY:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                listResult = new ArrayList<Map<String, Object>>();
                mapResult = new HashMap<String, Object>();
                mapResult.put("date",  myParsedItem.getValueByName("date"));
                mapResult.put("info", myParsedItem.getValueByName("detail"));
                listResult.add(mapResult);
                for (int i = 1; i < size; i++) {
                    mapResult = new HashMap<String, Object>();
                    mapResult.put("date",  myParsedItem.getValueByName("date" + i));
                    mapResult.put("info", myParsedItem.getValueByName("detail" + i));
                    listResult.add(mapResult);
                }
                success = size > 0;
            } else {
             success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, listResult, null);
            }
            break;
        case NET_WORK_ID_GET_RANK:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                listResult = new ArrayList<Map<String, Object>>();
                mapResult = new HashMap<String, Object>();
                mapResult.put("icon",  mCurBitmaps[0]);
                mapResult.put("title", myParsedItem.getValueByName("name"));
                mapResult.put("credit",  myParsedItem.getValueByName("credit"));
                listResult.add(mapResult);
                for (int i = 1; i < size; i++) {
                    mapResult = new HashMap<String, Object>();
                    mapResult.put("icon",  mCurBitmaps[i]);
                    mapResult.put("title", myParsedItem.getValueByName("name" + i));
                    mapResult.put("credit",  myParsedItem.getValueByName("credit" + i));
                    listResult.add(mapResult);
                }
                success = size > 0;
            } else {
                 success = false;
               }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, listResult, mCurBitmaps);
            }
            break;
        case NET_WORK_ID_GET_RULES:
            stringResult = myParsedItem.getValueByName("rules");
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, ((stringResult != null)&&(stringResult.length() > 0)), stringResult, null);
            }
            break;
        case NET_WORK_ID_GET_VERIFY_CODE:
            success = (Integer.valueOf(myParsedItem.getValueByName("result")) == 1);
            stringResult = myParsedItem.getValueByName("vcode");
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, stringResult, null);
            }
            break;
        case NET_WORK_ID_DOWNLOAD_FILES:
            if (mCallBack != null) {
                if ((attach > 0) && (attach < 100)) {
                    mCallBack.onNetworkCallBack(NET_WORK_ID_DOWNLOAD_FILES, false, attach, null);
                } else {
                    mCallBack.onNetworkCallBack(NET_WORK_ID_DOWNLOAD_FILES, true, 100, getDownloadFilePath());
                }
            }
            break;
        case NET_WORK_ID_GET_APP_COMMENTS:
            if (isValidValue(myParsedItem.getValueByName("list_size"))) {
                size = Integer.valueOf(myParsedItem.getValueByName("list_size"));
                listResult = new ArrayList<Map<String, Object>>();
                mapResult = new HashMap<String, Object>();
                mapResult.put("icon",  mCurBitmaps[0]);
                mapResult.put("nick", myParsedItem.getValueByName("name"));
                mapResult.put("comment",  myParsedItem.getValueByName("comment"));
                mapResult.put("date",  myParsedItem.getValueByName("time"));
                listResult.add(mapResult);
                for (int i = 1; i < size; i++) {
                    mapResult = new HashMap<String, Object>();
                    mapResult.put("icon",  mCurBitmaps[i]);
                    mapResult.put("nick", myParsedItem.getValueByName("name" + i));
                    mapResult.put("comment",  myParsedItem.getValueByName("comment" + i));
                    mapResult.put("date",  myParsedItem.getValueByName("time" + i));
                    listResult.add(mapResult);
                }
                success = size > 0;
            } else {
                success = false;
            }
            if (mCallBack != null) {
                mCallBack.onNetworkCallBack(OP, success, listResult, null);
            }
            break;
        }
    }

    private void beginNetTransaction(final String reqPath, final int OP) {
        //if (checkNetWorkSync() != NetworkConfigBase.NET_READY) {
        //  if (mCallBack != null) {
        //        mCallBack.onNetworkCallBack(OP, false, null, null);
        //    }
        //}
        new Thread(new Runnable() {

            @Override
            public void run() {
                mH.sendMessage(mH.obtainMessage(NET_WORK_MESSAGE_NET_BEGIN, 0, 0));
                mCurBitmaps = null;
                myXMLUtil.ParseXMLFromPath(myXMLParser, reqPath);
                myParsedItem = myXMLParser.getParsedData();
                mCurBitmaps = getImageFromXml();
                mH.sendMessage(mH.obtainMessage(NET_WORK_MESSAGE_NET_FINISH, OP, 0));
            }
        }).start();
    }

    private boolean isValidValue(String value) {
        if (value == null) {
            return false;
        } else if (value.length() <= 0) {
            return false;
        } else {
            return true;
        }
    }

    private Bitmap[] getImageFromXml() {
        int size = -1;
        Bitmap[] ret = null;
        String sizeInString = myParsedItem.getValueByName("list_size");

        if (sizeInString == null) {
            return null;
        } else if (sizeInString.length() <= 0) {
            return null;
        } else {
            size = Integer.valueOf(sizeInString);
        }

        if ((size <= 0)
                ||(myParsedItem.getValueByName("icon") == null)){
            return null;
        } else {
            ret = new Bitmap[size];
            ret[0] = downloadBitmapSync(myParsedItem.getValueByName("icon"));
            for (int i = 1; i < size; i++) {
                ret[i] = downloadBitmapSync(myParsedItem.getValueByName("icon" + i));
            }
        }

        return ret;
    }

    private Bitmap downloadBitmapSync (String path) {

        URL url;
        try {
            url = new URL(path);
            HttpURLConnection conn;
            conn = (HttpURLConnection)url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream inputStream=conn.getInputStream();
            return BitmapFactory.decodeStream(inputStream);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public void loginAsync(String userid, String imsi) {
        // TODO Auto-generated method stub
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_LOGIN), NET_WORK_ID_LOGIN);

        return;
    }

    @Override
    public void getSupportPhonesAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_PHONES), NET_WORK_ID_GET_SUPPORT_PHONES);

        return;
    }

    @Override
    public void getNewMsgAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_NEW_MSG), NET_WORK_ID_GET_NEW_MSG);

        return;
    }

    @Override
    public void getAllMsgAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_ALL_MSG), NET_WORK_ID_GET_ALL_MSG);

        return;
    }

    @Override
    public void searchAsync(int userid, String key) {
        // TODO Auto-generated method stub
        return;
    }

    @Override
    public void getPopWordsAsync(int userid, int number) {
        // TODO Auto-generated method stub
        return;
    }

    @Override
    public void getUserInfoAsync(int userid) {

        if (userid == -1) {
            return;
        }
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_USER_INFO), NET_WORK_ID_GET_USER_INFO);

        return;
    }

    @Override
    public void getExchangeListAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_EXCHANGE_LIST), NET_WORK_ID_GET_EXCHANGE_LIST);

        return;
    }

    @Override
    public void getVerifyCodeAsync() {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_VERIFY_CODE), NET_WORK_ID_GET_VERIFY_CODE);

        return;
    }

    @Override
    public void creditExchangeAsync(int userid, int itemid, String vcode) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_EXCHANGE_CREDIT), NET_WORK_ID_CREDIT_EXCHANGE);

        return;
    }

    @Override
    public void getExchangeHistoryListAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_EXCHANGE_HISTORY), NET_WORK_ID_GET_EXCHANGE_HISTORY);

        return;
    }

    @Override
    public void getRankAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_RANK), NET_WORK_ID_GET_RANK);

        return;
    }

    @Override
    public void getRulesAsync(int userid) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_RULES), NET_WORK_ID_GET_RULES);

        return;
    }

    @Override
    public void setUserInfoAsync(int userid, int gender, String nick, int icon) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_SET_USER_INFO), NET_WORK_ID_SET_USER_INFO);

        return;
    }

    @Override
    public void changePSWAsync(int userid, String psw, String vcode) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_SET_USER_PASSWORD), NET_WORK_ID_SET_USER_PSW);

        return;
    }

    @Override
    public void registerAsync(String userid, String psw) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_LOGIN), NET_WORK_ID_REGISTER);

        return;
    }

    @Override
    public void getAppComments(String userid, String appId, int number) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_GET_APP_COMMENTS), NET_WORK_ID_GET_APP_COMMENTS);

        return;
    }

    @Override
    public void publishComments(String userid, String comments) {
        if (NetworkConfigBase.DEMO)
            beginNetTransaction(MockRequestPathGenerater.generatePath(MockRequestPathGenerater.MOCK_NET_REQUEST_PATH_LOGIN), NET_WORK_ID_PUBLISH_COMMENTS);

        return;
    }

    private String getDownloadFilePath() {
        return mFilePath;
    }

    private void setDownloadFilePath(String path) {
        mFilePath = path;
    }

    public void downloadWithPercentCallback(final String url, final String path) {

        new Thread(new Runnable() {

            @Override
            public void run() {
                String filename=url.substring(url.lastIndexOf("/") + 1);
                URL myURL;
                try {
                    myURL = new URL(url);
                    URLConnection conn = myURL.openConnection();
                    conn.connect();
                    InputStream is = conn.getInputStream();
                    int fileSize = conn.getContentLength();
                    if (fileSize <= 0) throw new RuntimeException("Invalid Size");
                    if (is == null) throw new RuntimeException("stream is null");
                    String LocalPath = path + filename;
                    setDownloadFilePath(LocalPath);
                    FileOutputStream fos = new FileOutputStream(LocalPath);
                    byte buf[] = new byte[102400];
                    int downLoadFileSize = 0;
                    int percent = 0;
                    do {
                        int numread = is.read(buf);
                        if (numread == -1) {
                          break;
                        }
                        fos.write(buf, 0, numread);
                        downLoadFileSize += numread;
                        int cur = (downLoadFileSize * 100)/fileSize;
                        if(cur > percent) {
                            percent = percent + 10;
                            if (percent != 100) {
                                mH.sendMessage(mH.obtainMessage(NET_WORK_MESSAGE_NET_FINISH, NET_WORK_ID_DOWNLOAD_FILES, percent));
                            }
                        }
                      } while (true);
                    is.close();
                    fos.close();
                    mH.sendMessage(mH.obtainMessage(NET_WORK_MESSAGE_NET_FINISH, NET_WORK_ID_DOWNLOAD_FILES, 100));
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }  catch (Exception ex) {
                }
            }
        }).start();
    }

    @Override
    public int checkNetWorkSync() {
        URL url;
        int ret = -1;
        try {
            url = new URL("http://tianyi-treasured-book.googlecode.com/svn/trunk/");
            HttpURLConnection conn;
            for (int i = 0; i < 100; i ++) {
            conn = (HttpURLConnection)url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            ret = conn.getResponseCode();
            if (ret == 200)
                break;
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return (ret == 200)?NetworkConfigBase.NET_READY:NetworkConfigBase.NET_SERVER_BLOCKING;
    }
}
